/*Yipeng Huang and Scott Rogowski*/
/*yh2315 smr2167*/

//The register memory is the 'register' in the decode stage of the Mips pipeline.  It can read up to two registers at once and will return a 'read_valid' if the register has been writted to since the last reset.  It can write one register at a time.
module RegisterMemory (
						read_0_enable,read_0_index,read_0_valid,read_0_value,
						read_1_enable,read_1_index,read_1_valid,read_1_value,
						write_enable,write_index,write_data,
						reset,clk,
						enable_wait_for, set_wait_for, waiting_on_writeback
						);


	//Reading
	input read_0_enable;
	input [4:0] read_0_index;
	output read_0_valid;
	output [31:0] read_0_value;
	
	input read_1_enable;
	input [4:0] read_1_index;
	output read_1_valid;
	output [31:0] read_1_value;

	//Writing
	input write_enable;
	input [4:0] write_index;
	input [31:0] write_data;
		
	//Basic
	input reset;
	input clk;
	
	//Hazard detection.  Used by the hazard detection unit to decide whether to stall the next instructions.
	input enable_wait_for;
	input [4:0] set_wait_for;
	output [31:0] waiting_on_writeback;
		
	//Decode the write address
	wire [31:0] write_enable_decoded;
	Decoder writeDecoder (.decoder_in(write_index), .decoder_out(write_enable_decoded));	
	
	//Decode the start waiting address
	wire [31:0] start_waiting_mid;
	wire [31:0] start_waiting;
	Decoder waitDecoder (.decoder_in(set_wait_for), .decoder_out(start_waiting_mid));
	assign start_waiting = start_waiting_mid & enable_wait_for;
	
	reg [31:0] read_0_value_mid;
	reg [31:0] read_1_value_mid;
	reg read_0_valid_mid;
	reg read_1_valid_mid;
	
	//Sorry, this HAS TO BE a generate block.  Otherwise, it compiles in Leda but we get a "Slices of unpacked net arrays are not yet supported" in VCS
	genvar i;	
	generate
		for (i=0; i<32; i=i+1) begin: lin
			wire read_valid;
			wire [31:0] read_value;
			Line myline (	
					.clk(clk), .reset(reset), //basic inputs
					.write_enable(write_enable_decoded[i]), .write_data(write_data), //inputs
					.read_valid(read_valid), .read_value(read_value), //outputs
					.start_waiting(start_waiting[i]), .is_waiting(waiting_on_writeback[i])
					);
			always @(*) begin
				if (read_0_index==i && read_0_enable) begin
					read_0_value_mid = read_value;
					read_0_valid_mid = read_valid;
					end
				if (read_1_index==i && read_1_enable) begin
					read_1_value_mid = read_value;
					read_1_valid_mid = read_valid;
					end
				end
			end
		endgenerate

	assign read_0_value = read_0_value_mid;
	assign read_0_valid = read_0_valid_mid;
	assign read_1_value = read_1_value_mid;
	assign read_1_valid = read_1_valid_mid;
	
	
endmodule
